package com.bsoft.gol.hcs.utils;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.Map;
import java.util.Vector;

/**
 * Created by Administrator on 2016/5/31.
 */
public class ParameterRequestWrapper extends HttpServletRequestWrapper {

	private String body;

	private Map<String, String[]> params;

	public ParameterRequestWrapper(HttpServletRequest request, Map<String, String[]> newParams) throws IOException {
		super(request);

		StringBuilder stringBuilder = new StringBuilder();
		BufferedReader bufferedReader = null;
		try {
			InputStream inputStream = request.getInputStream();
			if (inputStream != null) {
				bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
				char[] charBuffer = new char[128];
				int bytesRead = -1;
				while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
					stringBuilder.append(charBuffer, 0, bytesRead);
				}
			}
		} catch (IOException ex) {
			throw ex;
		} finally {
			if (bufferedReader != null) {
				try {
					bufferedReader.close();
				} catch (IOException ex) {
					throw ex;
				}
			}
		}
		String bodyStr = stringBuilder.toString();
		body = bodyStr.startsWith("[") && bodyStr.endsWith("]") ? bodyStr.substring(1, bodyStr.length() - 1) : bodyStr;

		this.params = newParams;

		// RequestDispatcher.forward parameter
		renewParameterMap(request);
	}

	@Override
	public String getParameter(String name) {
		String result = "";

		Object v = params.get(name);
		if (v == null) {
			result = null;
		} else if (v instanceof String[]) {
			String[] strArr = (String[]) v;
			if (strArr.length > 0) {
				try {
					result = URLDecoder.decode(strArr[0], "utf-8");
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}
			} else {
				result = null;
			}
		} else if (v instanceof String) {
			result = (String) v;
			try {
				result = URLDecoder.decode(result, "utf-8");
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		} else {
			result = v.toString();
		}

		return result;
	}

	@Override
	public Map<String, String[]> getParameterMap() {
		return params;
	}

	@Override
	public Enumeration<String> getParameterNames() {
		return new Vector<String>(params.keySet()).elements();
	}

	@Override
	public String[] getParameterValues(String name) {
		String[] result = null;

		Object v = params.get(name);
		if (v == null) {
			result = null;
		} else if (v instanceof String[]) {
			result = (String[]) v;
			for (int i = 0; i < result.length; i++) {
				try {
					result[i] = URLDecoder.decode(result[i], "utf-8");
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}
			}
		} else if (v instanceof String) {
			try {
				result = new String[]{URLDecoder.decode((String) v, "utf-8")};
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		} else {
			try {
				result = new String[]{URLDecoder.decode(v.toString(), "utf-8")};
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}

		return result;
	}

	private void renewParameterMap(HttpServletRequest req) {

		String queryString = req.getQueryString();

		if (queryString != null && queryString.trim().length() > 0) {
			String[] params = queryString.split("&");

			for (int i = 0; i < params.length; i++) {
				int splitIndex = params[i].indexOf("=");
				if (splitIndex == -1) {
					continue;
				}

				String key = params[i].substring(0, splitIndex);

				if (!this.params.containsKey(key)) {
					if (splitIndex < params[i].length()) {
						String value = params[i].substring(splitIndex + 1);
						try {
							this.params.put(key, new String[]{URLDecoder.decode(value, "utf-8")});
						} catch (UnsupportedEncodingException e) {
							e.printStackTrace();
						}
					}
				}
			}
		}
	}

	@Override
	public ServletInputStream getInputStream() throws IOException {
		final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes("UTF-8"));
		ServletInputStream servletInputStream = new ServletInputStream() {
			@Override
			public boolean isFinished() {
				return false;
			}

			@Override
			public boolean isReady() {
				return false;
			}

			@Override
			public void setReadListener(ReadListener readListener) {

			}

			@Override
			public int read() throws IOException {
				return byteArrayInputStream.read();
			}
		};
		return servletInputStream;
	}

	@Override
	public BufferedReader getReader() throws IOException {
		return new BufferedReader(new InputStreamReader(this.getInputStream(), "UTF-8"));
	}

	public String getBody() {
		return this.body;
	}

	public void setBody(String body) {
		this.body = body;
	}
}
